package com.t.bricks.bussiness.service.wechat.impl;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.t.bricks.bussiness.model.wechat.SendMsg;
import com.t.bricks.bussiness.service.wechat.TimingService;
import com.t.bricks.bussiness.service.wechat.WeChatService;
import com.t.bricks.model.Log;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.json.JacksonShell;
import com.t.bricks.utils.spring.ModuleUtil;

/**
 * 定时处理服务,用于定时处理程序的定时任务
 */
@Service
public class TimingServiceImpl implements TimingService {
	
	/**
	 * 最后执行的时间
	 */
	private static LocalDateTime lastTime = null;
	
	/**
	 * 累计执行的次数
	 */
	private static long totalEvent = 0;
	
	/**
	 * 执行的阀门,如果为1则阻止请求,防止并发
	 */
	private static int isRun = 0;
	
	/**
	 * 启动循环线程的阀门,如果为1则阻止创建线程
	 */
	private static int isThreadRun = 0;
	
	/**
	 * 消息错误次数阈值(大于多少次则不进行发送)
	 */
	@Value("${app.pusmsg.ierror.total:5}")
	private Integer iErrorTotal;
	
	@Autowired
	private WeChatService weChatService;
	
	/**
	 * 开始执行
	 * 定时执行的方式存在消耗资源的问题,所以目前将其禁止
	 */
	//@Autowired//考虑到性能问题,目前禁用,改用数据库触发方式
	@Override
	public MsgEmity start() {
		if (1 == isThreadRun) {
			return MsgEmity.success(8999, "执行中");
		}
		
		isThreadRun = 1;
		
		ModuleUtil.runThread(() -> {
			try {
				doTiming();
			} catch (Exception e) {
				Log.error("执行消息处理时发生异常:", e.getMessage());
			} finally {
				isThreadRun = 0;//无论如何都要置为 "空闲"
			}
		});
		
		return MsgEmity.success(8999, "启动成功");
	}
	
	/**
	 * 服务信息(供外部检查使用)
	 * @return
	 */
	@Override
	public MsgEmity info() {
		String msg = new StringBuilder()
			.append("{")
			.append("\"lastTime\":\"").append(lastTime == null ? "null" : lastTime.toString()).append("\",")
			.append("\"totalEvent\":\"").append(totalEvent).append("\",")
			.append("\"isRun\":\"").append(isRun).append("\",")
			.append("\"now\":\"").append(LocalDateTime.now().toString()).append("\"")
			.append("}").toString();
	
		return new MsgEmity(true, "请求成功", msg);
	}
	
	/**
	 * 处理的任务,执行完当前查询到的数据后,还要再查一次,直到没有数据要处理为止
	 * @return
	 */
	private boolean doTiming() {
		int i = 0;
		while(true) {//直到所有待发送的信息都处理了再退出
			MsgEmity me = ModuleUtil.callServiceMethod("SendMsgService", "findByWait", iErrorTotal);
			if (null == me || !me.isSuccess()) {
				break;//有可能数据不存在,但是还是要返回true
			}
			
			String jsonStr = JacksonShell.toJSONString(me.getData());//返回的对象必须进行json转换
			List<SendMsg> list = JacksonShell.toJavaList(jsonStr, SendMsg.class);
			if (list.size() < 1) {
				//ThreadUtil.sleepThread(10000);//没有数据,休眠久一些 采用触发方式调用本函数的,不需要休眠,若是使用定时器方式则需要考虑使用本休眠
				break;
			}
			
			i++;
			for (SendMsg sendMsg : list) {
				weChatService.pushMsg(sendMsg, false);
			}
			
			if (i == 10) {
				break;//为了防止调用的方法本身存在问题导致数据一直都不为空,则进行这个判断,使其跳出循环
			}
		}
		
		lastTime = LocalDateTime.now();//最后执行的时间
		
		return true;//正常必须要返回true,否则定时线程将结束
	}

	/**
	 * 将所有待处理的消息全部进行处理
	 * 要使用@Autowired,所以不能带参数
	 * @return
	 */
	@Autowired//程序启动后自动执行,只执行一次
	private MsgEmity autoHandleMsg() {
		return handleMsg(null);
	}
	
	/**
	 * 将所有待处理的消息全部进行处理
	 * @param data 请求内容
	 * @return
	 */
	@Override
	public MsgEmity handleMsg(String data) {
		if (1 == isThreadRun) {
			return MsgEmity.success(8999, "调用成功,已在执行中");
		}
		
		isThreadRun = 1;

		ModuleUtil.runThread(() -> {
			try {
				if (null == lastTime) {//刚启动,不要马上运行
					Thread.sleep(60000);//等待1分钟应该也能启动了
				}
				doTiming();
			} catch (Exception e) {
				Log.error("执行消息处理时发生异常:", e.getMessage());
			} finally {
				isThreadRun = 0;//无论如何都要置为 "空闲"
			}
		});
		
		return MsgEmity.success(8999, "调用成功,正在处理");
	}

}
